﻿using System;
using System.Windows.Forms;
using AForge.Video.DirectShow;
using System.Camera.Monitor;
using System.Camera.Broadcast;

namespace ViewCam
{
    public partial class CameraForm : Form
    {
        public CameraForm()
        {
            InitializeComponent();
        }

        #region Properties

        TimeForm timeSched;

        public Int32 AutoNotifyStop { get; set; }

        public Int32 AutoRecordStop { get; set; }

        public Int32 BeepDura { get; set; }

        public Int32 BeepFreq { get; set; }

        public string CamName { get; set; }

        public int CamOrder { get; set; }

        public string CamType { get; set; }

        public ToolStripComboBox cmbCamera { get; set; }

        public DateTime endTime { get; set; }

        public string RecordPath { get; set; }

        public DateTime startTime { get; set; }

        public string Title { get; set; }
        #endregion

        #region Declarations
        CameraClient client;
        CameraMonitor moncam;
        ViewCamHelper viewcamModule;
        private FilterInfoCollection webcam;
        #endregion

        #region Controls
        /// <summary>
        /// Handles the CheckedChanged event of the AutoRecord control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void AutoRecord_CheckedChanged(object sender, EventArgs e)
        {
            if (((CheckBox)sender).Checked)
            {
                this.toggleOption(1, true);
                SetStatus("Automatic Recording Enabled.");
            }
            else
            {
                this.toggleOption(1, false);
                SetStatus("Automatic Recording Disabled.");
            }
        }

        /// <summary>
        /// Handles the CheckedChanged event of the BeepOnMotion control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void BeepOnMotion_CheckedChanged(object sender, EventArgs e)
        {
            if (((CheckBox)sender).Checked)
            {
                this.toggleOption(2, true);
                SetStatus("Beep On Motion Enabled.");
            }
            else
            {
                this.toggleOption(2, false);
                SetStatus("Beep On Motion Disabled.");
            }
        }

        /// <summary>
        /// Handles the Click event of the btnClose control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void btnClose_Click(object sender, EventArgs e)
        {
            Shutdown();
            this.Close();
        }

        /// <summary>
        /// Handles the FormClosing event of the CameraForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
       private void CameraForm_FormClosed(object sender, EventArgs e)
        {
            Shutdown();
        }

        /// <summary>
        /// Handles the Click event of the btnConnect control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (this.txtIPAddress.Text != "")
            {
                if (this.btnConnect.Text == "Connect")
                {
                    this.client.Connect(txtIPAddress.Text, 8080);
                    this.btnConnect.Text = "Disconnect";
                    SetStatus("Transmit Data Disconnected.");
                }
                else
                {
                    this.client.Disconnect();
                    this.btnConnect.Text = "Connect";
                    SetStatus("Transmit Data Connect.");
                }
            }
            else
            {
                MessageBox.Show("No IP Address!", "View Cam", MessageBoxButtons.OK);
            }
        }

        /// <summary>
        /// Handles the Click event of the btnRecord control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void btnRecord_Click(object sender, EventArgs e)
        {
            if (this.moncam.IsRecording)
            {
                this.moncam.StopRecording();
                this.moncam.forceRecord = false;
                this.btnRecord.Text = "Record";
                SetStatus("Manual Record Started.");
            }
            else
            {
                this.moncam.StartRecording();
                this.moncam.forceRecord = true;
                this.btnRecord.Text = "Stop";
                SetStatus("Manual Record Stopped.");
            }
        }

        /// <summary>
        /// Handles the Click event of the btnSchedule control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void btnSchedule_Click(object sender, EventArgs e)
        {
            timeSched = new TimeForm();
            timeSched.camForm = this;
            timeSched.ShowDialog();

            if (startTime != null & endTime != null)
            {
                if (startTime < endTime)
                {
                    SetStatus("Scheduled Recording: Starts at " + startTime.ToLongTimeString() + " | Ends at " + endTime.ToLongTimeString());
                    DisableControlOnSchedule();
                    EnableTimerOnSchedule();
                }
                else
                {
                    SetStatus("Time Not Properly Set. Start Time must be greater than Time Right Now and End Time.");
                }
            }
        }

        /// <summary>
        /// Handles the Load event of the CameraForm control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void CameraForm_Load(object sender, EventArgs e)
        {
            if (CamType == "WebCam")
            {
                webcam = new FilterInfoCollection(FilterCategory.VideoInputDevice);
                loadCamera(webcam);
            }
            
            setupOptions(false);
            LoadToolTips();
            SetTheme();
            SetStatus("Ready");
        }

        /// <summary>
        /// Handles the CheckedChanged event of the MotionDetection control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void MotionDetection_CheckedChanged(object sender, EventArgs e)
        {
            if (((CheckBox)sender).Checked)
            {
                this.toggleOption(0, true);
                SetStatus("Motion Detection Enabled.");
            }
            else
            {
                this.toggleOption(0, false);
                SetStatus("Motion Detection Disabled.");
            }
        }

        /// <summary>
        /// Handles the Tick event of the timer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        private void timer_Tick(object sender, EventArgs e)
        {
            if (DateTime.Now.ToLongTimeString() == startTime.ToLongTimeString())
            {
                this.moncam.StartRecording();
                this.moncam.forceRecord = true;
            }

            if (DateTime.Now.ToLongTimeString() == endTime.ToLongTimeString())
            {
                this.moncam.StopRecording();
                this.moncam.forceRecord = false;
                DisableTimerOnSchedule();
                EnableControlOnSchedule();
                SetStatus("Scheduled Recording Completed.");
            }
        }
        
        #endregion

        #region Methods
        /// <summary>
        /// Shutdowns this instance.
        /// </summary>
        public void Shutdown()
        {
            viewcamModule = new ViewCamHelper();
            viewcamModule.LoadWebCam(cmbCamera);

            this.moncam.StopRecording();
            this.moncam.StopCapture();
        }

        /// <summary>
        /// Disables the control on schedule.
        /// </summary>
        private void DisableControlOnSchedule()
        {
            this.btnRecord.Enabled = false;
            //this.btnClose.Enabled = false;
            this.grpOptions.Enabled = false;
        }

        /// <summary>
        /// Disables the timer on schedule.
        /// </summary>
        private void DisableTimerOnSchedule()
        {
            timer.Enabled = false;
        }

        /// <summary>
        /// Enables the control on schedule.
        /// </summary>
        private void EnableControlOnSchedule()
        {
            this.btnRecord.Enabled = true;
            //this.btnClose.Enabled = true;
            this.grpOptions.Enabled = true;
        }

        /// <summary>
        /// Enables the timer on schedule.
        /// </summary>
        private void EnableTimerOnSchedule()
        {
            timer.Interval = 100;
            timer.Enabled = true;
        }

        /// <summary>
        /// Loads the camera.
        /// </summary>
        /// <param name="xcam">The xcam.</param>
        private void loadCamera(FilterInfoCollection xcam)
        {
            try
            {
                this.Text = "Camera Name: " + Title;
                this.picBox.SizeMode = PictureBoxSizeMode.StretchImage;
                this.moncam = new CameraMonitor(this.picBox, xcam[CamOrder].MonikerString, CamName);
                this.moncam.RecordingPath = RecordPath;
                this.moncam.BeepFreq = BeepFreq;
                this.moncam.BeepDura = BeepDura;
                this.moncam.AutoRecordStop = AutoRecordStop;
                this.moncam.AutoNotifyStop = AutoNotifyStop;

                this.client = new CameraClient(this.picBox);
                this.client.CameraOutputSize = this.picBox.Size;
            }
            catch (Exception)
            { }
        }

        /// <summary>
        /// Loads the tool tips.
        /// </summary>
        private void LoadToolTips()
        {
            ShowToolTip("Records video via a Scheduled Time.", btnSchedule);
            ShowToolTip("Records video via User Dependent.", btnRecord);
            ShowToolTip("Relays the video to the desired IP address.", btnConnect);
            ShowToolTip("Closes this window. Dropping any connection.", btnClose);
            ShowToolTip("Input IP Address.", txtIPAddress);
            ShowToolTip("Toggle checkbox to Detect Motion.", MotionDetection);
            ShowToolTip("Toggle checkbox to beep if motion is detected.", BeepOnMotion);
            ShowToolTip("Toggle checkbox to automatically record if motion is detected.", AutoRecord);
        }

        /// <summary>
        /// Sets the status.
        /// </summary>
        /// <param name="message">The message.</param>
        private void SetStatus(string message)
        {
            this.lblCamStatus.Text = message;
        }

        /// <summary>
        /// Sets the theme.
        /// </summary>
        private void SetTheme()
        {
            viewcamModule = new ViewCamHelper();
            this.BackColor = viewcamModule.SetThemeColor(lblStatus);
        }

        /// <summary>
        /// Setups the options.
        /// </summary>
        /// <param name="value">if set to <c>true</c> [value].</param>
        private void setupOptions(bool value)
        {
            this.BeepOnMotion.Enabled = value;
            this.AutoRecord.Enabled = value;

            if (value == false)
            {
                this.BeepOnMotion.Checked = value;
                this.AutoRecord.Checked = value;
            }
        }

        /// <summary>
        /// Shows the tool tip.
        /// </summary>
        /// <param name="msg">The MSG.</param>
        /// <param name="btn">The BTN.</param>
        private void ShowToolTip(string msg, Control btn)
        {
            viewcamModule = new ViewCamHelper();
            viewcamModule.EnableToolTip(msg, btn, toolTip);
        }

        /// <summary>
        /// Toggles the option.
        /// </summary>
        /// <param name="optionIndex">Index of the option.</param>
        /// <param name="value">if set to <c>true</c> [value].</param>
        private void toggleOption(int optionIndex, bool value)
        {
            switch (optionIndex)
            {
                case 0:
                    this.moncam.MotionDetection = value;
                    setupOptions(value);
                    break;
                case 1:
                    this.moncam.RecordOnMotion = value;
                    break;
                case 2:
                    this.moncam.BeepOnMotion = value;
                    break;
            }
        }
        #endregion
    }
}
